
package com.idealighter.game.games.fqzs.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.core.constant.room.RoomActiveConstant;
import com.idealighter.game.dictionary.dic.SharkRoomTypeDic;
import com.idealighter.game.dictionary.dic.SharkTimeDic;
import com.idealighter.game.dictionary.domain.SharkRoomDomain;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.RoomState;
import com.idealighter.game.games.fqzs.dto.BetInfo;
import com.idealighter.game.games.fqzs.dto.IconRateInfo;
import com.idealighter.game.games.fqzs.dto.RoomInfo;
import com.idealighter.game.games.fqzs.dto.RoomTypeDetailInfo;
import com.idealighter.game.games.fqzs.message.ResApplyBankersMsg;
import com.idealighter.game.games.fqzs.message.ResBankerInfoMsg;
import com.idealighter.game.games.fqzs.message.ResBetMsg;
import com.idealighter.game.games.fqzs.message.ResBetStageMsg;
import com.idealighter.game.games.fqzs.message.ResChipsChangeMsg;
import com.idealighter.game.games.fqzs.message.ResClearBetMsg;
import com.idealighter.game.games.fqzs.message.ResEnterGameHallMsg;
import com.idealighter.game.games.fqzs.message.ResEnterRoomMsg;
import com.idealighter.game.games.fqzs.message.ResExitRoomMsg;
import com.idealighter.game.games.fqzs.message.ResExitTableMsg;
import com.idealighter.game.games.fqzs.message.ResFastEnterTableMsg;
import com.idealighter.game.games.fqzs.message.ResGameStageMsg;
import com.idealighter.game.games.fqzs.message.ResGameStageMsg.TopRewardItemDto;
import com.idealighter.game.games.fqzs.message.ResRestStageMsg;
import com.idealighter.game.games.fqzs.message.ResTableBetInfosMsg;
import com.idealighter.game.games.fqzs.struct.SharkRoom;
import com.idealighter.game.games.fqzs.struct.SharkSeat;
import com.idealighter.game.games.fqzs.struct.SharkTable;
import com.idealighter.game.games.fqzs.struct.SharkTable.TopRewardItem;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.struct.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;

/**
 * 飞禽走兽消息管理 .
 * 
 * @date 2016年2月17日 下午1:02:17
 *
 */
@Singleton
public class SharkMsgMgr {

  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private SharkDataMgr dataMgr;
  @Inject
  private SharkRoomTypeDic roomTypeDic;
  @Inject
  private SharkTimeDic timeDic;

  /**
   * 发送进入游戏大厅消息.
   */
  public ResMessage sendEnterGameHallMsg() {
    ResEnterGameHallMsg msg = new ResEnterGameHallMsg();

    Collection<SharkRoom> rooms = dataMgr.newestRooms();
    for (SharkRoom room : rooms) {
      SharkRoomDomain roomDom = room.getRoomDomain();
      if (roomDom.getIsActive() != RoomActiveConstant.ACTIVE) {
        continue;
      }
      RoomTypeDetailInfo roomTypeDetailInfo = new RoomTypeDetailInfo();

      roomTypeDetailInfo.setType(roomDom.getType());
      roomTypeDetailInfo.setTypeName(roomTypeDic.map().get(roomDom.getType()).getName());

      RoomInfo roomInfo = new RoomInfo();
      roomInfo.setRoomId(room.getId().intValue());
      roomInfo.setName(roomDom.getName());
      roomInfo.setType(roomDom.getType());
      roomInfo.setMaxNum(roomDom.getMaxNum());
      roomInfo.setFree(roomDom.getFree());
      roomInfo.setGeneral(roomDom.getGeneral());
      roomInfo.setCrowded(roomDom.getCrowded());
      roomInfo.setLower(roomDom.getLower());
      roomInfo.setUpper(roomDom.getUpper());
      roomInfo.setProportionGold(roomDom.getProportionGold());
      roomInfo.setProportionChips(roomDom.getProportionChips());
      roomInfo.setTabble(roomDom.getTableNum());
      roomInfo.setMaxOne(roomDom.getMaxOne());
      roomInfo.setMinOne(roomDom.getMinOne());
      roomInfo.setAfee(roomDom.getAfee());
      roomInfo.setInType(roomDom.getInType());
      roomInfo.setPlayerNum(room.getPlayers().size());
      roomInfo.setStatus(roomStatus(room).desc);
      roomInfo.setDisplayNames(roomDom.getDisplays());
      roomInfo.setPlaceHolder(roomDom.getPlaceHolder());
      roomTypeDetailInfo.getRooms().add(roomInfo);

      msg.getRoomTypes().add(roomTypeDetailInfo);
    }

    return msg;
  }

  /**
   * 房间状态，空闲,普通,拥挤,爆满 .
   * 
   * @param room .
   * @return
   */
  private RoomState roomStatus(SharkRoom room) {
    int playersNum = room.getPlayers().size();
    SharkRoomDomain roomDom = room.getRoomDomain();

    if (playersNum < roomDom.getMaxNum() * roomDom.getFree() / 100) {
      return RoomState.IDLE;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getGeneral() / 100) {
      return RoomState.GENERAL;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getCrowded() / 100) {
      return RoomState.CROWD;
    } else {
      return RoomState.FULL;
    }

  }

  /**
   * 发送兑换筹码消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendChipsChangeMsg(SharkSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setChips(seat.getTotalChips());
    msg.setOrder(seat.getOrder());
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送休息阶段消息 .
   * 
   * @param table .
   * @param time .
   */
  public void sendRestStageMsg(SharkTable table, int time, SharkSeat seat) {
    ResRestStageMsg msg = new ResRestStageMsg();
    msg.setTime(time);

    for (Entry<Integer, Integer> iconRatEtr : table.getIconRates().entrySet()) {
      IconRateInfo iconRateInfo = new IconRateInfo();
      iconRateInfo.setIcon(iconRatEtr.getKey());
      iconRateInfo.setRate(iconRatEtr.getValue());
      msg.getIconRateInfos().add(iconRateInfo);
    }


    if (seat != null) {
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    } else {
      sendTablePlayersMsg(table, msg);
    }
  }

  /**
   * 发送下注阶段消息 .
   * 
   * @param table .
   * @param time .
   */
  public void sendBetStageMsg(SharkTable table, int time, SharkSeat seat) {
    ResBetStageMsg msg = new ResBetStageMsg();
    msg.setTime(time);
    for (Entry<Integer, Integer> iconRatEtr : table.getIconRates().entrySet()) {
      IconRateInfo iconRateInfo = new IconRateInfo();
      iconRateInfo.setIcon(iconRatEtr.getKey());
      iconRateInfo.setRate(iconRatEtr.getValue());
      msg.getIconRateInfos().add(iconRateInfo);
    }

    if (seat != null) {
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    } else {
      sendTablePlayersMsg(table, msg);
    }
  }

  /**
   * 发送游戏阶段消息 .
   * 
   * @param table .
   * @param iconIndex .
   */
  public void sendGameStageMsg(SharkTable table, int iconIndex, SharkSeat seat) {
    SharkSeat banker = table.getBanker();
    List<TopRewardItem> rewardList = table.getTopRewards();
    List<TopRewardItemDto> rewardListDto = new ArrayList<TopRewardItemDto>();
    for (TopRewardItem item : rewardList) {
      TopRewardItemDto resultItem = new TopRewardItemDto();

      resultItem.setChips(item.getChips());
      resultItem.setPlayerId(item.getId());
      resultItem.setNickName(item.getNickName());
      rewardListDto.add(resultItem);
    }

    if (seat != null) {
      ResGameStageMsg msg = new ResGameStageMsg();
      msg.setIconIndex(iconIndex);
      msg.setTime(timeDic.get(GameState.GAME.getStage()).getTime());

      msg.setBankerBillChips(banker.getBillChips());
      msg.setPlayerBillChips(seat.getBillChips());
      msg.setTopRewards(rewardListDto);
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    } else {
      for (SharkSeat s : table.getSeats()) {
        if (s.getPlayerId() == 0) {
          continue;
        }
        ResGameStageMsg msg = new ResGameStageMsg();
        msg.setIconIndex(iconIndex);
        msg.setTime(timeDic.get(GameState.GAME.getStage()).getTime());

        msg.setBankerBillChips(banker.getBillChips());
        msg.setPlayerBillChips(s.getBillChips());
        msg.setTopRewards(rewardListDto);
        msgWriter.writeMsg(s.getPlayerId(), msg);
      }
    }

  }

  /**
   * 发送申请庄家玩家列表消息 .
   * 
   * @param table .
   */
  public void sendApplyBankersMsg(SharkTable table) {
    ResApplyBankersMsg msg = new ResApplyBankersMsg();
    msg.setApplicants(new ArrayList<>(table.getApplyBankers()));
    sendTablePlayersMsg(table, msg);
  }


  /**
   * 发送申请庄家玩家列表消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendApplyBankersMsg(SharkSeat seat) {
    ResApplyBankersMsg msg = new ResApplyBankersMsg();
    msg.setApplicants(new ArrayList<>(seat.getTable().getApplyBankers()));
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送庄家信息 .
   * 
   * @param table .
   */
  public void sendBankerInfoMsg(SharkTable table) {
    SharkSeat banker = table.getBanker();
    ResBankerInfoMsg msg = new ResBankerInfoMsg();
    msg.setPlayerId(banker.getPlayerId());
    msg.setChips(banker.getTotalChips());
    msg.setName(banker.getPlayerName());
    msg.setNum(banker.getBankerNum());
    msg.setScore(banker.getBankerScore());
    sendTablePlayersMsg(table, msg);
  }


  /**
   * 发送庄家信息 .
   * 
   * @param seat 座位信息.
   */
  public void sendBankerInfoMsg(SharkSeat seat) {
    SharkSeat banker = seat.getTable().getBanker();
    ResBankerInfoMsg msg = new ResBankerInfoMsg();
    msg.setPlayerId(banker.getPlayerId());
    msg.setChips(banker.getTotalChips());
    msg.setName(banker.getPlayerName());
    msg.setNum(banker.getBankerNum());
    msg.setScore(banker.getBankerScore());
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送清空下注消息.
   * 
   * @param res 结果(0:成功,1:下注阶段不能清除下注)
   */
  public ResMessage sendClearBetMsg(int res) {
    ResClearBetMsg msg = new ResClearBetMsg();
    msg.setRes(res);
    return msg;
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   */
  public ResMessage sendEnterRoomMsg(Player player) {
    ResEnterRoomMsg msg = new ResEnterRoomMsg();
    for (AbstractTable table : player.curRoom.tables()) {
      msg.getTables().add(table.tableInfo());
    }
    msg.setMembers(player.curRoom.memInfos());
    return msg;
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public ResMessage sendFastEnterTableMsg(Player player, SharkTable table, long totalChips) {
    ResFastEnterTableMsg msg = new ResFastEnterTableMsg();
    AbstractRoom room = table.room();
    List<MemInfo> mems = new ArrayList<>();
    for (Long playerId : table.players()) {
      mems.add(room.memInfo(playerId));
    }
    msg.setMems(mems);
    msg.setTotalChips(totalChips);
    msg.setHistoryRewardIcons(new ArrayList<>(table.getHistoryRewardIcons()));
    return msg;
  }

  /**
   * 图标合计押注.
   * 
   * @param icon .
   * @param iconBet .
   */
  public ResMessage sendBetMsg(int icon, long iconBet) {
    ResBetMsg msg = new ResBetMsg();
    BetInfo betInfo = new BetInfo();
    betInfo.setIcon(icon);
    betInfo.setBet(iconBet);
    msg.setBetInfo(betInfo);
    return msg;
  }

  /**
   * 发送退出房间消息.
   * 
   * @param res 0:退出成功,1:在牌桌中退出失败
   */
  public ResMessage sendExitRoomMsg(int res) {
    ResExitRoomMsg msg = new ResExitRoomMsg();
    msg.setRes(res);
    return msg;
  }

  /**
   * 发送下注信息 .
   * 
   * @param table .
   */
  public void sendTableBetInfosMsg(SharkTable table) {
    ResTableBetInfosMsg msg = new ResTableBetInfosMsg();
    for (Entry<Integer, Long> tableBetEtr : table.getTableBets().entrySet()) {
      BetInfo betInfo = new BetInfo();
      betInfo.setIcon(tableBetEtr.getKey());
      betInfo.setBet(tableBetEtr.getValue());
      msg.getBetInfos().add(betInfo);
    }

    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送退出桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendExitTableMsg(SharkSeat seat) {
    ResExitTableMsg msg = new ResExitTableMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 向同桌的玩家(包括自己)发送消息 .
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(SharkTable table, ResMessage msg) {
    List<? extends AbstractSeat> seats = table.seats();
    for (int i = 0; i < seats.size(); i++) {
      AbstractSeat seat = seats.get(i);
      long playerId = seat.getPlayerId();
      if (playerId > 0) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

}
